# -*- coding: utf-8 -*-

#    OriginDB
#    Copyright (C) 2010  Jason Power <power.jg@gmail.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from PyQt4.QtGui import *
from PyQt4 import QtCore

from math import atan, pi, sqrt


class Bond(QGraphicsItem):

	pen = QPen()
	pen.setWidth(2)
	pen.setCapStyle(QtCore.Qt.RoundCap)

	spacing = 5
	padding = 10

	def __init__(self, bond, parent=None):
		self.selected = False
		
		self.bond = bond

		#print "Adding bond:", bond.GetIdx()

		self.beginAtom = parent.getAtom(self.bond.GetBeginAtomIdx())
		self.endAtom = parent.getAtom(self.bond.GetEndAtomIdx())
		if not self.beginAtom or not self.endAtom:
			raise Exception("Not enough atoms?")

		self.length = sqrt( (self.beginAtom.GetX()-self.endAtom.GetX())**2 +
						   (self.beginAtom.GetY()-self.endAtom.GetY())**2) * parent.scale
		self.height = self.padding*2 + self.pen.width()+2
		self.angle = 0

		QGraphicsItem.__init__(self, parent)

		self.setFlag(QGraphicsItem.ItemIsSelectable, True)

		self.computeGeometry()

	def setType(self, typ):
		if typ == "single":
			self.bond.UnsetHash()
			self.bond.UnsetWedge()
			self.bond.SetBO(1)
		elif typ == "double":
			self.bond.UnsetHash()
			self.bond.UnsetWedge()
			self.bond.SetBO(2)
		elif typ == "triple":
			self.bond.UnsetHash()
			self.bond.UnsetWedge()
			self.bond.SetBO(3)
		elif typ == "wedge":
			if self.bond.IsWedge():
				self.flipBond()
			else:
				self.bond.UnsetHash()
				self.bond.SetWedge()
				self.bond.SetBO(1)
		elif typ == "hash":
			if self.bond.IsHash():
				self.flipBond()
			else:
				self.bond.SetHash()
				self.bond.UnsetWedge()
				self.bond.SetBO(1)
		elif typ == "squiggle":
			self.bond.SetHash()
			self.bond.SetWedge()
			self.bond.SetBO(1)
		elif typ == "cistrans":
			self.bond.UnsetHash()
			self.bond.SetWedge()
			self.bond.SetBO(2)
		self.update()
		self.prepareGeometryChange()

	def flipBond(self):
		beginAtom = self.bond.GetBeginAtom()
		endAtom = self.bond.GetEndAtom()

		self.bond.SetBegin(endAtom)
		self.bond.SetEnd(beginAtom)

		self.beginAtom = endAtom
		self.endAtom = beginAtom

		self.computeGeometry()
		self.update()

	def atomMoved(self):
		self.computeGeometry()

	def computeGeometry(self):
		start = self.parentItem().translateFromAtomCoords([self.beginAtom.GetX(), self.beginAtom.GetY()])
		end = self.parentItem().translateFromAtomCoords([self.endAtom.GetX(), self.endAtom.GetY()])

		self.length = sqrt((start.x()-end.x())**2+(start.y()-end.y())**2)

		self.setPos(start + (end-start)*.5)
		v = end-start
		if v.x() != 0:
			angle = atan(v.y() / v.x())
		elif v.y() > 0:
			angle = pi/2
		else:
			angle = -pi/2
		if v.x() < 0:
			angle += pi

		self.rotate(angle*180/pi - self.angle)
		self.angle = angle*180/pi

		self.prepareGeometryChange()

	def setSelected(self, selected):
		self.selected = selected
		self.prepareGeometryChange()
		self.update()

	def boundingRect(self):
		width = self.length - self.padding*2
		right = 0
		left = 0
		if self.endAtom.GetAtomicNum()==6:
			right = self.padding
		if self.beginAtom.GetAtomicNum()==6:
			left = self.padding

		bo = self.bond.GetBO()
		if self.bond.IsWedge() or self.bond.IsHash():
			bo = 2
		
		height = 4 + (bo-1)*self.padding
		
		if self.selected:
			return QtCore.QRectF(-width/2.0-2-left, -height/2.0-2, width+4+right+left, height+4)
		else:
			return QtCore.QRectF(-width/2.0-left, -height/2.0, width+right+left, height)

	def paint(self, painter, option, widget):
		#print "drawing bond:", self.bond.GetIdx()
		painter.setRenderHint(QPainter.Antialiasing, True)
		
		if self.selected:
			painter.drawRect(self.boundingRect())

		painter.setPen(self.pen)
			
		order = self.bond.GetBO()

		startPadding = self.padding
		endPadding = self.padding

		# Don't draw carbon
		if self.endAtom.GetAtomicNum()==6:
			endPadding = 0
		if self.beginAtom.GetAtomicNum()==6:
			startPadding = 0

		startPos = QtCore.QPointF(-self.length/2.0, 0)
		endPos = QtCore.QPointF(self.length/2.0,0)
		pnorm = QtCore.QPointF(0, self.spacing)
		vn = QtCore.QPointF(1,0)

		if self.bond.IsWedge():
			painter.setBrush(QBrush(QColor(0,0,0)))
			painter.drawPolygon(startPos+vn*startPadding, endPos+pnorm-vn*endPadding, endPos-pnorm-vn*endPadding)
		elif self.bond.IsHash():
			v1 = startPos+vn*startPadding-(endPos+pnorm-vn*endPadding)
			v2 = startPos+vn*startPadding-(endPos-pnorm-vn*endPadding)
			painter.drawLine(endPos+pnorm-vn*endPadding, endPos-pnorm-vn*endPadding)
			painter.drawLine(endPos+pnorm-vn*endPadding+v1*.25, endPos-pnorm-vn*endPadding+v2*.25)
			painter.drawLine(endPos+pnorm-vn*endPadding+v1*.5, endPos-pnorm-vn*endPadding+v2*.5)
			painter.drawLine(endPos+pnorm-vn*endPadding+v1*.75, endPos-pnorm-vn*endPadding+v2*.75)
			painter.drawLine(endPos+pnorm-vn*endPadding+v1*.95, endPos-pnorm-vn*endPadding+v2*.95)
		elif order == 1:
			painter.drawLine(startPos+vn*startPadding, endPos-vn*endPadding)
		elif order == 2:
			painter.drawLine(startPos-pnorm*.5+vn*startPadding, endPos-pnorm*.5-vn*endPadding)
			painter.drawLine(startPos+pnorm*.5+vn*startPadding, endPos+pnorm*.5-vn*endPadding)
		elif order >= 3:
			painter.drawLine(startPos+vn*startPadding, endPos-vn*endPadding)
			painter.drawLine(startPos-pnorm+vn*startPadding, endPos-pnorm-vn*endPadding)
			painter.drawLine(startPos+pnorm+vn*startPadding, endPos+pnorm-vn*endPadding)